package com.kelp.codetoolkit.ui.form

import com.intellij.database.util.common.isNotNullOrEmpty
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.ComboBox
import com.intellij.openapi.ui.popup.JBPopup
import com.intellij.openapi.ui.popup.JBPopupFactory
import com.intellij.ui.JBColor
import com.intellij.ui.components.JBList
import com.intellij.ui.components.JBScrollPane
import com.intellij.ui.util.preferredWidth
import com.kelp.codetoolkit.cache.CollectionPsiClassCache
import com.kelp.codetoolkit.constant.MethodConstant
import com.kelp.codetoolkit.data.ListCellData
import com.kelp.codetoolkit.data.RequestParamDetailData
import com.kelp.codetoolkit.enums.JavaCollectionEnum
import com.kelp.codetoolkit.renderer.ParamClassListCellRenderer
import com.kelp.codetoolkit.respository.CodeToolkitGlobalSettingRepository
import com.kelp.codetoolkit.service.MethodDialogHandleService
import java.awt.Dimension
import java.awt.FlowLayout
import java.awt.event.KeyAdapter
import java.awt.event.KeyEvent
import javax.swing.*
import javax.swing.border.LineBorder
import javax.swing.event.DocumentEvent
import javax.swing.event.DocumentListener

/**
 * @author: liuyuebai
 * @date: 2025/1/25 09:55
 * @description:
 */
class MethodRequestTwoPanel(project: Project):JPanel() {

    private val requestParamData: RequestParamDetailData = RequestParamDetailData()

    private  val requestBoxModel: DefaultComboBoxModel<String> = DefaultComboBoxModel()
    private  val requestBoxKeyModel: DefaultComboBoxModel<String> = DefaultComboBoxModel(MethodConstant.getMapWrapperKey())
    private val requestParamLabel: JLabel = JLabel("Request        Param1         Class： ")
    private val requestParam: JTextField = JTextField(15)
    private val requestParamNameLabel: JLabel = JLabel("Request       Param1        Name：")
    private val requestParamName: JTextField = JTextField(15)
    private val requestBoxLabel: JLabel = JLabel("Param1 Class Collection Wrapper：")
    private val requestBox: ComboBox<String> = ComboBox(requestBoxModel)
    private val requestBoxKeyLabel: JLabel = JLabel("Param1 Class Map Wrapper Key：")
    private val requestBoxKey: ComboBox<String> = ComboBox(requestBoxKeyModel)

    private val requestParamListModel: DefaultListModel<ListCellData> = DefaultListModel()
    private val requestParamList: JList<ListCellData> = JBList(requestParamListModel)
    private val requestScrollPane: JScrollPane = JBScrollPane(requestParamList)

    private val requestParamPanel = JPanel(FlowLayout(FlowLayout.LEFT))

    private var requestCurrentPage = 0 // 当前页码，初始化为0
    private var requestTotalPages = 0 // 总页数，初始设为0，后续根据数据总量动态更新
    // 用于标记是否监听文档变化，初始化为true表示默认监听
    private var requestListenerEnabled = true

    private var methodWindowPopup: JBPopup? = null

    init {
        val selectCollectionWrapper = MethodConstant.getSelectCollectionWrapper()
        val state = CodeToolkitGlobalSettingRepository.getInstance(project).state
        if(state.getPageSetting().isNotNullOrEmpty){
            val pageArr = state.getPageSetting().split(".")
            if (pageArr.isNotEmpty()){
                selectCollectionWrapper.add(pageArr[pageArr.size - 1])
            }
        }
        selectCollectionWrapper.forEach { collectionWrapper-> requestBoxModel.addElement(collectionWrapper) }
        requestBox.preferredSize = Dimension(170,35)
        requestBoxKey.preferredSize = Dimension(170,35)
        requestBox.isEnabled = false
        requestBoxKey.isEnabled = false
        handleRequestParam(project)
    }

    fun getRequestPanel(): JPanel {
        requestParamPanel.layout = BoxLayout(requestParamPanel, BoxLayout.Y_AXIS) // 设置mainPanel的布局为垂直排列
        val oneLinePanel = JPanel(FlowLayout(FlowLayout.LEFT,5,5))
        oneLinePanel.add(requestParamLabel)
        oneLinePanel.add(Box.createHorizontalStrut(2)) // 添加空白间隔以改善对齐
        oneLinePanel.add(requestParam)
        oneLinePanel.add(Box.createHorizontalStrut(10)) // 添加空白间隔以改善对齐
        oneLinePanel.add(requestParamNameLabel)
        oneLinePanel.add(Box.createHorizontalStrut(2)) // 添加空白间隔以改善对齐
        oneLinePanel.add(requestParamName)
        val twoLinePanel = JPanel(FlowLayout(FlowLayout.LEFT,5,5))
        twoLinePanel.add(requestBoxLabel)
        twoLinePanel.add(Box.createHorizontalStrut(2)) // 添加空白间隔以改善对齐
        twoLinePanel.add(requestBox)
        twoLinePanel.add(Box.createHorizontalStrut(10)) // 添加空白间隔以改善对齐
        twoLinePanel.add(requestBoxKeyLabel)
        twoLinePanel.add(Box.createHorizontalStrut(2)) // 添加空白间隔以改善对齐
        twoLinePanel.add(requestBoxKey)
        requestParamPanel.add(oneLinePanel)
        requestParamPanel.add(twoLinePanel)
        // 定义浅灰色
        val lightGray = JBColor.GRAY
        // 创建宽度为 1 像素、颜色为浅灰色的 LineBorder
        val lineBorder = LineBorder(lightGray, 1)
        // 创建带有标题的边框，使用上面创建的 LineBorder 作为边框
        val titledBorder = BorderFactory.createTitledBorder(lineBorder, "Request Param2")
        requestParamPanel.setBorder(titledBorder)
        return requestParamPanel
    }

    fun getRequestParamData(): RequestParamDetailData {
        requestParamData.requestParamName = requestParamName.text
        return requestParamData
    }

    private fun handleRequestParam(project: Project){
        // 为requestPBoxOne添加监听器，根据其值控制requestPBoxKeyOne的显示
        requestBox.addActionListener {
            val selectedItem = requestBox.selectedItem as String
            requestBoxKey.isEnabled = selectedItem  == "Map"
            val collectionEnum = JavaCollectionEnum.getByName(selectedItem)
            if (null != collectionEnum) {
                requestParamData.collectionName = collectionEnum.collectionName
                val psiClass = CollectionPsiClassCache.getCache(project, collectionEnum.qualifiedName)
                requestParamData.collectionParamPsiClass = psiClass
            }
        }

        requestBoxKey.addActionListener {
            val selectedItem = requestBoxKey.selectedItem as String
            requestParamData.mapKey = selectedItem
        }

        val listener = object : DocumentListener {
            override fun insertUpdate(e: DocumentEvent) {
                println("requestParamOne insertUpdate isDocumentListenerEnabled:$requestListenerEnabled")
                if (!requestListenerEnabled){
                    return
                }
                commonHandleRequest(project)
            }
            override fun removeUpdate(e: DocumentEvent) {
                println("requestParamOne removeUpdate isDocumentListenerEnabled:$requestListenerEnabled")
                if (!requestListenerEnabled){
                    return
                }
                commonHandleRequest(project)
            }
            override fun changedUpdate(e: DocumentEvent) {
                println("requestParamOne changedUpdate isDocumentListenerEnabled:$requestListenerEnabled")
                if (!requestListenerEnabled){
                    return
                }
                commonHandleRequest(project)
            }
        }
        // 添加请求参数文档监听器到输入框
        requestParam.document.addDocumentListener(listener)

        //添加键盘按键监听
        requestParam.addKeyListener(object : KeyAdapter() {
            override fun keyTyped(e: KeyEvent) {
                println("requestParamOne addKeyListener keyTyped: ${e.keyChar}")
                requestListenerEnabled = true
            }
            override fun keyPressed(e: KeyEvent) {
                println("requestParamOne addKeyListener keyPressed: ${e.keyCode}")
                requestListenerEnabled = true
            }
            override fun keyReleased(e: KeyEvent) {
                println("requestParamOne addKeyListener keyReleased: ${e.keyCode}")
                requestListenerEnabled = true
            }
        })

        // 添加选择事件监听器
        requestParamList.addListSelectionListener {
            if (!it.valueIsAdjusting) {
                val selectedIndex = requestParamList.selectedIndex
                if (selectedIndex!= -1) {
                    requestScrollPane.isVisible = false
                    methodWindowPopup?.closeOk(null)
                    requestListenerEnabled = false
                    val selectData = requestParamListModel.elementAt(selectedIndex)
                    requestParam.text = selectData?.shortClassName
                    requestParamData.shortClassName = selectData?.shortClassName?:""
                    requestParamData.paramClass = selectData?.psiClass
                    requestBox.isEnabled = true
                }
            }
        }
        // 添加滚动监听器到responseScrollPane
        var previousScrollPosition = 0 // 初始化上一次滚动位置
        var previousPage = 0
        // 添加滚动监听器到selectScrollPane
        requestScrollPane.viewport.addChangeListener { e ->
            println("responseScrollPane addChangeListener isDocumentListenerEnabled:$requestListenerEnabled")
            if (!requestListenerEnabled){
                return@addChangeListener
            }
            val viewport = e.source as JViewport
            val viewportHeight = viewport.extentSize.height
            val maxScrollPosition = viewport.viewSize.height - viewportHeight
            val currentScrollPosition = viewport.viewPosition.y
            val thresholdTop = 1 // 距离顶部的阈值，可根据实际情况调整
            val thresholdBottom = 1 // 距离底部的阈值，可根据实际情况调整

            // 检测滚动方向
            if (currentScrollPosition < previousScrollPosition - thresholdTop && requestCurrentPage > 1) {
                // 向上滚动，向上翻页
                requestCurrentPage--
                println("requestOneScrollPane addChangeListener scrolling up $requestCurrentPage")
            } else if (currentScrollPosition >= maxScrollPosition - thresholdBottom && requestCurrentPage < requestTotalPages) {
                // 向下滚动，向下翻页
                requestCurrentPage++
                if (requestCurrentPage >= requestTotalPages){
                    requestCurrentPage = requestTotalPages
                }
                println("requestOneScrollPane addChangeListener scrolling down ${requestCurrentPage}")
            }
            // 更新上一次滚动位置
            previousScrollPosition = currentScrollPosition

            // 根据新的页码执行搜索
            if (requestCurrentPage != previousPage) { // 假设previousPage是跟踪上一次页码的变量
                commonHandle(project)
                // 更新previousPage
                previousPage = requestCurrentPage
            }
        }
    }

    private fun commonHandleRequest(project: Project){
        requestCurrentPage = 0
        requestParamListModel.clear()
        commonHandle(project)
        methodParamPopWindow(requestParam,requestParamList, requestScrollPane)
    }

    private fun commonHandle(project: Project){
        val methodDialogHandleService = MethodDialogHandleService.getInstance(project)
        val dataList = methodDialogHandleService.filterSearchByCache(requestParam.text,project)
        requestTotalPages = dataList.size / MethodConstant.getCommonPageSize() + 1
        val searchPageData = methodDialogHandleService.assembleCellData(dataList,requestCurrentPage, project)
        requestParamListModel.addAll(searchPageData)
    }

    private fun methodParamPopWindow(paramField: JTextField, selectList: JList<ListCellData>, paramScrollPane: JScrollPane){
        methodWindowPopup?.closeOk(null)
        selectList.setVisibleRowCount(MethodConstant.getCommonPageSize())
        paramScrollPane.preferredSize = Dimension(500, 300)
        paramScrollPane.viewport.view = selectList
        val cellRenderer = ParamClassListCellRenderer()
        cellRenderer.setParamScrollPane(paramScrollPane)
        selectList.cellRenderer = cellRenderer
        paramScrollPane.isVisible = true
        val popupFactory = JBPopupFactory.getInstance()
        methodWindowPopup = popupFactory.createComponentPopupBuilder(paramScrollPane, null)
            .setResizable(true)
            .setMovable(true)
            .createPopup()
        methodWindowPopup!!.showUnderneathOf(paramField)
    }
}